﻿#region Header

/*
Remote views based on linq
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using InterLinq.Client;
using InterLinq.Objects;
using InterLinq.Server.Services.Impl;
using InterLinq.Services.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sebarf.Client;
using Sebarf.Configuration;
using Sebarf.Core;
using Sebarf.Core.Internal;
using Sebarf.ProcessChains.Interfaces;
using Sebarf.Profiles.WPF;
using Sebarf.Server;
using Sebarf.Services.Impl;
using Sebarf.Services.Interfaces;
using Sebastof.Server.Services.Impl;
using Sebastof.Services.Interfaces;

#endregion

namespace InterLinq.Sebarf.Test {
	/// <summary>
	/// Description of the class
	/// </summary>
	[TestClass]
	public class TestRequest {
		#region Public Properties

		// public Properties located here

		#endregion

		#region Public Methods

		[TestMethod]
		[DeploymentItem("InterLinq.Sebarf.Test.CachelessProfile.xaml")]
		[DeploymentItem("InterLinq.Sebarf.Test.CachelessProfile_Server.xaml")]
		[DeploymentItem("InterLinq.Sebarf.Test.RequestHandler.xaml")]
		public void RunTest() {
			var queryHandler = new ObjectQueryHandler(new Persons());
			IServer server = WcfBasedServer.Create(delegate {
				// create the base service
				var locator = new ServiceRegistrationLocatorService();
				// register backend locator service
				locator.RegisterService(new BackendProviderService());
				// register query handler locator service
				locator.RegisterService(new QueryHandlerLocatorService { QueryHandler = queryHandler });
				// create engine
				RequestHandlerEngine toReturn = RequestHandlerEngine.Create(locator,
																			 RequestHandlerLoader
																				.Load(
																				"InterLinq.Sebarf.Test.RequestHandler.xaml"));
				// add interlinq handler
				locator.GetRegisteredService<IAddRequestHandlerService>().
					AddAddionalHandler(new ExecuteLinqQueryRequestHandler { QueryHandler = queryHandler });
				// set backend provider
				locator.GetRegisteredService<IBackendProviderRegisterService>().
					SetBackendProvider(queryHandler);
				return toReturn;
			});
			server.Start();

			var clientServiceLocator = new ServiceRegistrationLocatorService();

			IClient client = WcfBasedClient.Create("Client 1",
													RequestHandlerEngine.Create(clientServiceLocator,
																				 RequestHandlerLoader.Load(
																					"InterLinq.Sebarf.Test.RequestHandler.xaml")));
			client.Connect();

			// load profiles
			client.Process(new WpfBasedProfileLoadRequest { ProfileId = "Profile", ResourceFileName = "InterLinq.Sebarf.Test.CachelessProfile_Server.xaml" });
			client.ProcessLocal(new WpfBasedProfileLoadRequest { ProfileId = "Profile", ResourceFileName = "InterLinq.Sebarf.Test.CachelessProfile.xaml" });

			// populate remote engine
			clientServiceLocator.GetRegisteredService<IRequestRemoteHandlerEngineLocatorService>().SetRemoteEngine(client);

			// create client datacontext
			var ctx = new MyDataContext {
				QueryHandler =
					new InterLinqQueryHandler(
					new InterLinqQueryProvider(new SebarfBasedLinqQueryGateway(clientServiceLocator, client)))
			};
			clientServiceLocator.RegisterService(new QueryHandlerLocatorService { QueryHandler = ctx.QueryHandler });

			// ensure dependencies
			client.Process(new ResolveServicesDependenciesRequest());
			client.Process(new ResolveProcessChainDependenciesRequest());
			client.ProcessLocal(new ResolveServicesDependenciesRequest());
			client.ProcessLocal(new ResolveProcessChainDependenciesRequest());

			// startup services
			client.Process(new SetupServicesRequest());
			client.ProcessLocal(new SetupServicesRequest());

			int count = ctx.Persons.Count();
			Assert.AreEqual(count, 1);
			Assert.AreEqual(ctx.Persons.ToArray()[0].Name, "Raphael");

			server.Stop();
		}

		#endregion

		#region Nested type: MyDataContext

		public class MyDataContext : ClientContext {
			public IQueryable<Person> Persons {
				get { return QueryHandler.GetTable<Person>().AsQueryable(); }
			}
		}

		#endregion

		#region Nested type: Persons

		public class Persons : IObjectSource {
			private readonly ReaderWriterLock _lock = new ReaderWriterLock();

			#region IObjectSource Members

			public ReaderWriterLock Lock {
				get { return _lock; }
			}

			public IEnumerable<T> GetObjects<T>() {
				if (typeof(T) == typeof(Person)) {
					return (IEnumerable<T>)new[] { new Person { Name = "Raphael" } }.AsEnumerable();
				}
				return null;
			}

			public void AddObject<T>(T obj) {
				throw new NotImplementedException();
			}

			public void AddObject(Type type, object obj) {
				throw new NotImplementedException();
			}

			public void DeleteObject(Type type, object obj) {
				throw new NotImplementedException();
			}

			#endregion
		}

		#endregion
	}

	#region Public Classes

	[Serializable]
	public class Person : SebastofApplicationObject {
		public string Name {
			get { return GetValue<String>("Name"); }
			set { SetValue("Name", value); }
		}
	}

	#endregion
}